#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>

/* 这是一个创建了n个进程组成的进程链的程序，其中n是命令行参数*/
// 在该函数中会使用wait函数使父进程阻塞

pid_t r_wait(int *stat_loc){
	int retval;

	while( ( (retval = wait(stat_loc)) == -1) && (errno == EINTR) );
	return retval;
}


int main(int argc, char *argv[]){
	pid_t child_pid;
	int i,n;

	/* 检查有效的命令行参数数量*/
	if(argc != 2){
		fprintf(stderr, "Usage: %s processes\n", argv[0]);
		return 1;
	}

	n = atoi(argv[1]);

	for(i=0; i<n; ++i){
		// 如果创建进入子进程，则退出循环
		if(child_pid = fork() <= 0){
			break;
		}		
	}

	// 等待所有的子进程，此时会在所有子线程都退出后打印其信息
	// 如果不使用while循环，则一个父进程最多等待一个子进程。如果信号恰好在第一个子进程结束前出现，则父进程实际上就不会等待任何一个子进程了
	while(r_wait(NULL) > 0);
	
	// 这里使用fprintf进行输出是因为在默认情况下，系统会对写入stdout中的输出进行缓冲
	// 这样特定的消息可能就不会在printf函数之后立即出现了。
	// 写入stderr的消息不会被缓冲，而是被立即写入。因此，在调试消息中应该总是使用stderr
	fprintf(stderr, "i:%d process ID: %ld parent ID: %ld child ID:%ld\n",
					i, (long)getpid(), (long)getppid(), (long)child_pid);

	//printf("i:%d process ID: %ld parent ID: %ld child ID:%ld\n",
	//				i, (long)getpid(), (long)getppid(), (long)child_pid);
	return 0;
}

